#include "img_file.h"

QMap<int, QString> img_Info::DATA_TYPE = QMap<int, QString> {
    {0, "unknown"},
    {1, "bool"},
    {2, "unsigned char"},
    {4, "signed short"},
    {8, "signed int"},
    {16, "float"},
    {32, "complex"},
    {64, "double"},
    {128, "rgb"},
    {255, "all"},
    {256, "signed char"},
    {512, "unsigned short"},
    {768, "unsigned int"},
    {1024, "long long"},
    {1280, "unsigned long long"},
    {1536, "long double"},
    {1792, "double pair"},
    {2048, "long double pair"},
    {2304, "rgba"}
};

QMap<int, QString> img_Info::UNIT = QMap<int, QString> {
    {0, "Unknown"},
    {1, "Meter (m)"},
    {2, "Milimeter (mm)"},
    {3, "Micron (µm)"},
    {8, "Seconds (s)"},
    {16, "Miliseconds (ms)"},
    {24, "Microseconds (µs)"},
    {32, "Hertz (Hz)"},
    {40, "Parts-per-million (ppm)"},
    {48, "Radians per second (rad/s)"}
};

QMap<int, img_WL> img_Info::IMG_WL = QMap<int, img_WL> {
    {0, img_WL("肺窗", 1750, -525)},
    {1, img_WL("纵隔窗", 300, 40)},
    {2, img_WL("骨窗", 1250, 300)},
    {3, img_WL("软组织窗", 400, 50)}
};

img_File::img_File(const QString & fileName, QObject * parent)
    : QObject(parent)
    , OPENED_FLAG(false)
{
    if(fileName.isEmpty()) {
        return;
    }
    this->openFile(fileName);
}

img_File::~img_File()
{
    if(QFileInfo(sys_Data::getInstance()->getAnalysisAlgPath() + "/temp.nii").isFile()) {
        QFile::remove(sys_Data::getInstance()->getAnalysisAlgPath() + "/temp.nii");
    }
}

void img_File::openFile(const QString & fileName)
{
    this->name = fileName;
    QFileInfo fileInfo(fileName);
    if(fileInfo.suffix() == "dcm") {
        covDCMFile(fileInfo.absolutePath());
    } else {
        readFile(fileName);
    }
}

img_Info const & img_File::info() const
{
    return this->fileInfo;
}

vtkImageData * const img_File::image()
{
    if(this->imgData == nullptr) {
        vtkSmartPointer<vtkImageReslice> reslice = vtkSmartPointer<vtkImageReslice>::New();
        vtkSmartPointer<vtkTransform> trsform = vtkSmartPointer<vtkTransform>::New();
        trsform->RotateX(180);
        trsform->RotateZ(180);
        trsform->Translate(fileReader->GetOutput()->GetCenter());
        reslice->SetInputData(fileReader->GetOutput());
        reslice->SetResliceTransform(trsform);
        reslice->SetAutoCropOutput(1);
        reslice->Update();
        imgData = reslice->GetOutput();
        imgData->SetOrigin(0, 0, 0);
    }
    return this->imgData;
}

vtkNIFTIImageReader * const img_File::reader() const
{
    return this->fileReader;
}

QString const &img_File::getFileName() const
{
    return this->name;
}

void img_File::setFileInfo()
{
    imgHeader = this->fileReader->GetNIFTIHeader();
    fileInfo.fileSize = QFileInfo(this->fileInfo.fileName).size();
    fileInfo.dimInfo = imgHeader->GetDimInfo();
    imgHeader->GetVoxOffset();
    for(int i = 0; i < 8; i++) {
        fileInfo.dim[i] = imgHeader->GetDim(i);
        fileInfo.pixdim[i] = imgHeader->GetPixDim(i);
    }
    imgHeader->GetSRowX(fileInfo.srow[0]);
    imgHeader->GetSRowY(fileInfo.srow[1]);
    imgHeader->GetSRowZ(fileInfo.srow[2]);
    fileInfo.voxOffset = imgHeader->GetVoxOffset();
    fileInfo.dataType = imgHeader->GetDataType();
    fileInfo.bitPix = imgHeader->GetBitPix();
    fileInfo.sclSlope = imgHeader->GetSclSlope();
    fileInfo.sclInter = imgHeader->GetSclInter();
    fileInfo.descrip = imgHeader->GetDescrip();
    fileInfo.auxFile = imgHeader->GetAuxFile();
    fileInfo.qFormCode = imgHeader->GetQFormCode();
    fileInfo.sFormCode = imgHeader->GetSFormCode();
    fileInfo.qOffset[0] = imgHeader->GetQOffsetX();
    fileInfo.qOffset[1] = imgHeader->GetQOffsetY();
    fileInfo.qOffset[2] = imgHeader->GetQOffsetZ();
    fileInfo.xyzt_units = imgHeader->GetXYZTUnits();
}

void img_File::covDCMFile(const QString &filePath)
{
    QProcess process;
    process.setWorkingDirectory(sys_Data::getInstance()->getAnalysisAlgPath());
    process.start(
        QString("%1/python.exe %2 %3\n").arg(
            sys_Data::getInstance()->getCondaEnvir(),
            "dcm2nii.py", filePath).toStdString().c_str());
    process.waitForFinished();
    process.close();
    readFile(sys_Data::getInstance()->getAnalysisAlgPath() + "/temp.nii");
}

void img_File::readFile(const QString &fileName)
{
    OPENED_FLAG = true;
    imgData = nullptr;
    fileInfo.fileName = fileName;
    this->fileReader = vtkSmartPointer<vtkNIFTIImageReader>::New();
    this->fileReader->SetDataByteOrderToLittleEndian();
    this->fileReader->SetFileName(fileName.toStdString().c_str());
    this->fileReader->SetDataSpacing(3.2, 3.2, 1.5);
    this->fileReader->Update();
    this->setFileInfo();
}

double img_File::getLevel() const
{
    return level;
}

bool img_File::isOpen() const
{
    return OPENED_FLAG;
}

void img_File::clear()
{
    OPENED_FLAG = false;
}

double img_File::getWindow() const
{
    return window;
}

const QString img_Info::toQString() const
{
    QStringList info;
    info << QString("<file name: \"%1\">").arg(fileName);
    info << QString("<file size: %1KB>").arg(fileSize >> 10);
    info << QString("<dim info: %1>").arg(dimInfo);
    info << QString("<dim: %1 %2 %3 %4 %5 %6 %7 %8>").
         arg(dim[0]).arg(dim[1]).arg(dim[2]).arg(dim[3]).arg(dim[4]).arg(dim[5]).arg(dim[6]).arg(dim[7]);
    info << QString("<pixdim: %1 %2 %3 %4 %5 %6 %7 %8>").
         arg(pixdim[0]).arg(pixdim[1]).arg(pixdim[2]).arg(pixdim[3]).arg(pixdim[4]).arg(pixdim[5]).arg(pixdim[6]).arg(pixdim[7]);
    info << QString("<vox offset: %1, data type: %2, bit pix: %3>").arg(voxOffset).arg(dataType).arg(bitPix);
    info << QString("<scl slope: %1, scl inter: %2>").arg(sclSlope).arg(sclInter);
    info << QString("<descrip: \"%1\">").arg(descrip);
    info << QString("<aux file: \"%1\">").arg(auxFile);
    info << QString("<qFormCode: %1, sFromCode: %2>").arg(qFormCode).arg(sFormCode);
    info << QString("<qOffset: %1 %2 %3>").arg(qOffset[0]).arg(qOffset[1]).arg(qOffset[2]);
    info << QString("<srow_x: %1 %2 %3 %4>").arg(srow[0][0]).arg(srow[0][1]).arg(srow[0][2]).arg(srow[0][3]);
    info << QString("<srow_y: %1 %2 %3 %4>").arg(srow[1][0]).arg(srow[1][1]).arg(srow[1][2]).arg(srow[1][3]);
    info << QString("<srow_z: %1 %2 %3 %4>").arg(srow[2][0]).arg(srow[2][1]).arg(srow[2][2]).arg(srow[2][3]);
    info << QString("<xyzt_units: %1>").arg(xyzt_units);
    return info.join('\n');
}
